package wang.woran.sudoku;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.TilePane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class JavaFXUI extends Application {
    private final int START_X = 5;
    private final int START_Y = 5;
    private final int SIDE_LENGTH = 40;
    private List<Button> buttons = new ArrayList<>();
    private int count = 0;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        BorderPane borderPane = new BorderPane();
        MenuBar menuBar = createMenu();
        borderPane.setTop(menuBar);
        Pane pane = createContents();
        borderPane.setCenter(pane);
        Scene scene = new Scene(borderPane, 370, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private MenuBar createMenu() {
        MenuBar menuBar = new MenuBar();
        Menu startMenu = new Menu("开始");
        Menu helpMenu = new Menu("帮助");
        menuBar.getMenus().addAll(startMenu, helpMenu);

        MenuItem askMenu = new MenuItem("问");
        askMenu.setOnAction((event) -> {
            buttons.forEach((btn) -> {
                btn.setText("");
            });
            setValue(11, 7);
            setValue(12, 9);
            setValue(18, 8);
            setValue(19, 9);
            setValue(23, 5);
            setValue(25, 7);
            setValue(28, 5);
            setValue(35, 2);
            setValue(36, 2);
            setValue(42, 8);
            setValue(44, 1);
            setValue(46, 6);
            setValue(48, 3);
            setValue(49, 1);
            setValue(52, 9);
            setValue(57, 1);
            setValue(58, 9);
            setValue(64, 2);
            setValue(71, 6);
            setValue(72, 6);
            setValue(74, 3);
            setValue(75, 8);
        });

        MenuItem answerMenu = new MenuItem("答");
        answerMenu.setOnAction((event) -> {
            final Map<Integer, Integer> queue = new ConcurrentHashMap<>();
            count = 0;
            Thread t = new Thread(() -> {
                int[] sudoku = getCurrentSudoku();
                Answer answer = new Answer();
                answer.go(sudoku, (index, value) -> {
                    count++;
                    // System.out.println(index + "," + value);
                    if (count % 100 == 0) {
                        Platform.runLater(() -> {
                            for (Integer i : queue.keySet()) {
                                Button btn = buttons.get(i);
                                int v = queue.get(i);
                                if (v == 0) {
                                    btn.setText("");
                                } else {
                                    btn.setText(v + "");
                                }
                            }
                        });
                    } else {
                        queue.put(index, value);
                    }
                });
                Platform.runLater(() -> {
                    for (Integer i : queue.keySet()) {
                        Button btn = buttons.get(i);
                        int v = queue.get(i);
                        if (v == 0) {
                            btn.setText("");
                        } else {
                            btn.setText(v + "");
                        }
                    }
                });
            });
            t.start();
        });
        startMenu.getItems().addAll(askMenu, answerMenu);

        MenuItem aboutMenu = new MenuItem("关于");
        helpMenu.getItems().add(aboutMenu);
        return menuBar;
    }

    private Pane createContents() {
        AnchorPane board = new AnchorPane();
        board.setMaxSize(370, 370);
        board.setPrefSize(370, 370);

        TilePane tilePane = new TilePane();
        tilePane.setPrefColumns(9);
        tilePane.setPrefRows(9);
        tilePane.setHgap(1);
        tilePane.setVgap(1);
        board.getChildren().add(tilePane);
        AnchorPane.setBottomAnchor(tilePane, 5D);
        AnchorPane.setLeftAnchor(tilePane, 5D);
        AnchorPane.setRightAnchor(tilePane, 5D);
        AnchorPane.setTopAnchor(tilePane, 5D);

        for (int i = 0; i < 81; i++) {
            Button button = new Button();
            button.setPrefSize(SIDE_LENGTH - 1, SIDE_LENGTH - 1);
            button.setStyle("-fx-font: 18 arial;-fx-text-fill:black");
            buttons.add(button);
            button.setOnKeyReleased((event -> {
                String text = event.getText();
                if (text != null && !text.equals("")) {
                    if ("123456789".indexOf(event.getText()) != -1) {
                        button.setText(event.getText());
                        if (!checkTheSudoku()) {
                            button.setStyle("-fx-font: 18 arial;-fx-text-fill:red");
                        } else {
                            button.setStyle("-fx-font: 18 arial;-fx-text-fill:black");
                        }
                    } else {

                    }
                }
            }));
            tilePane.getChildren().add(button);
        }
        for (int i = 0; i < 10; i++) {
            Line line = new Line(START_X, START_Y + i * SIDE_LENGTH, START_X + SIDE_LENGTH * 9,
                    START_Y + i * SIDE_LENGTH);
            if (i % 3 != 0) {
                line.setStrokeWidth(0.5);
            }
            board.getChildren().add(line);
        }
        for (int i = 0; i < 10; i++) {
            Line line = new Line(START_X + SIDE_LENGTH * i, START_Y, START_X + SIDE_LENGTH * i,
                    START_Y + SIDE_LENGTH * 9);
            if (i % 3 != 0) {
                line.setStrokeWidth(0.5);
            }
            board.getChildren().add(line);
        }
        return board;
    }

    private boolean checkTheSudoku() {
        int[] sudoku = getCurrentSudoku();
        Answer answer = new Answer();
        return answer.check(sudoku);
    }

    private int[] getCurrentSudoku() {
        int[] sudoku = new int[81];
        for (int i = 0; i < 81; i++) {
            Button btn = buttons.get(i);
            String text = btn.getText();
            if (text.equals("")) {
                sudoku[i] = 0;
            } else {
                sudoku[i] = Integer.valueOf(text);
            }
        }
        return sudoku;
    }

    private void setValue(int index, int value) {
        if (value == 0) {
            buttons.get(index).setText("");
        } else {
            buttons.get(index).setText(value + "");
            buttons.get(index).setStyle("-fx-font: 18 arial;-fx-text-fill:blue");
        }
    }

    private void setCandidate(int index, List<Integer> values) {
        // buttons.get(index).setText("1 2 3\n4 5 6\n7 8 9");
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 9; i++) {
            int v = values.get(i);
            if (v == i) {
                sb.append(v + "");
            } else {
                sb.append(" ");
            }
            if (v % 3 == 0) {
                sb.append("\n");
            } else {
                sb.append("  ");
            }
        }
        buttons.get(index).setText(sb.toString());
        buttons.get(index).setStyle("-fx-font: 9 arial;-fx-text-fill:blue");
    }

}
